import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

// ignore: must_be_immutable
class Universal extends StatelessWidget {
  Universal({
    Key? key,
    this.builder,
    this.child,
    this.children,
    bool? isScroll = false,
    bool? isStack = false,
    bool? enabled = false,
    bool? addInkWell = false,
    bool? noScrollBehavior = false,
    bool? reverse = false,
    bool? primary = false,
    bool? visible = true,
    this.stackFit,
    this.alignment,
    this.widthFactor,
    this.heightFactor,
    MainAxisAlignment? mainAxisAlignment,
    CrossAxisAlignment? crossAxisAlignment,
    Axis? direction,
    this.textBaseline,
    VerticalDirection? verticalDirection,
    this.textDirection,
    MainAxisSize? mainAxisSize,
    this.clipBehavior,
    this.margin,
    this.padding,
    bool? expand = false,
    bool? shrink = false,
    BorderRadius? borderRadius,
    this.size,
    this.width,
    this.height,
    this.color,
    this.onTap,
    this.onDoubleTap,
    this.onLongPress,
    this.onTapDown,
    this.onTapCancel,
    this.excludeFromSemantics,
    this.onTapUp,
    this.decoration,
    this.onHighlightChanged,
    this.onHover,
    this.focusColor,
    this.hoverColor,
    this.highlightColor,
    this.splashColor,
    this.splashFactory,
    this.radius,
    this.customBorder,
    this.enableFeedback,
    this.focusNode,
    this.canRequestFocus,
    this.onFocusChange,
    this.autoFocus,
    this.physics,
    this.scrollController,
    this.opacity,
    Widget? replacement,
  })  : isStack = isStack ?? false,
        isScroll = isScroll ?? false,
        noScrollBehavior = noScrollBehavior ?? true,
        visible = visible ?? true,
        direction = direction ?? Axis.vertical,
        mainAxisAlignment = mainAxisAlignment ?? MainAxisAlignment.start,
        crossAxisAlignment = crossAxisAlignment ?? CrossAxisAlignment.center,
        mainAxisSize = mainAxisSize ?? MainAxisSize.max,
        enabled = enabled ?? false,
        expand = expand ?? false,
        shrink = shrink ?? false,
        addInkWell = addInkWell ?? false,
        reverse = reverse ?? false,
        primary = primary ?? false,
        verticalDirection = verticalDirection ?? VerticalDirection.down,
        borderRadius = borderRadius ?? BorderRadius.zero,
        replacement = replacement ?? const SizedBox.shrink(),
        assert(!(addInkWell ?? false)),
        super(key: key);
  final Widget? child;
  final List<Widget>? children;
  final StatefulWidgetBuilder? builder;

  ///  ****** [Stack] ******  ///
  final bool isStack;
  final StackFit? stackFit;

  /// 控制剪辑方式
  /// [Clip.none]没有剪辑        最快
  /// [Clip.hardEdge]不抗锯齿    快
  /// [Clip.antiAlias]抗锯齿     慢
  /// [Clip.antiAliasWithSaveLayer]抗锯齿和saveLayer  很慢
  /// 使用到的组件[Stack]、[ClipRRect]、[ClipPath]、[ClipRect]、[ClipOval]
  /// 、[Container]、[Material]、[Card]、[Stack]、[SingleChildScrollView]
  final Clip? clipBehavior;

  ///  ****** [Align] ******  ///
  final AlignmentGeometry? alignment;
  final double? widthFactor;
  final double? heightFactor;

  ///  ****** [Flex]=[Column]+[Row] ******  ///
  final MainAxisAlignment? mainAxisAlignment;
  final CrossAxisAlignment? crossAxisAlignment;
  final Axis direction;
  final TextBaseline? textBaseline;
  final VerticalDirection verticalDirection;
  final TextDirection? textDirection;
  final MainAxisSize? mainAxisSize;

  ///  ****** [Padding] ******  ///
  final EdgeInsetsGeometry? margin;
  final EdgeInsetsGeometry? padding;

  ///  ****** [SingleChildScrollView] ******  ///
  ///  移出头部和底部蓝色阴影
  final bool noScrollBehavior;
  final bool isScroll;
  final ScrollPhysics? physics;
  final ScrollController? scrollController;
  final bool reverse;
  final bool primary;

  ///  ****** [SizedBox] ******  ///
  final bool expand;
  final bool shrink;
  final Size? size;
  final double? width;
  final double? height;

  ///  ****** [Opacity] ******  ///
  final double? opacity;

  ///  ****** [ColoredBox]||[DecoratedBox] ******  ///
  final Color? color;

  /// [addInkWell]添加[InkWell] 有水波纹效果
  final bool addInkWell;

  /// [enabled]默认为false [addInkWell]默认为false
  /// ([enabled]=false || [addInkWell]=true ) 除[onTap]外[GestureDetector]属性无效
  /// ([enabled]=true && [addInkWell]=false ) [GestureDetector]属性全部有效
  final bool enabled;

  ///  短暂触摸屏幕时触发
  final GestureTapCallback? onTap;

  ///  用户在短时间内触摸了屏幕两次
  final GestureTapCallback? onDoubleTap;

  ///  用户触摸屏幕时间超过500ms时触发
  final GestureLongPressCallback? onLongPress;

  ///  用户每次和屏幕交互时都会被调用
  final GestureTapDownCallback? onTapDown;

  ///  短暂触摸屏幕时触发取消
  final GestureTapCancelCallback? onTapCancel;

  final bool? excludeFromSemantics;

  ///  ****** [GestureDetector] ******  ///
  ///  点击抬起
  final GestureTapUpCallback? onTapUp;

  ///  ****** [DecoratedBox] ******  ///
  final Decoration? decoration;

  ///  ****** 点击事件相关 ******  ///
  ///  ****** [InkWell] ******  ///
  ///  高亮变化回调
  ///  当材料的这一部分突出显示或停止突出显示时调用
  final ValueChanged<bool>? onHighlightChanged;

  ///  当指针进入或退出墨水响应区域时调用
  final ValueChanged<bool>? onHover;

  ///  获取焦点颜色
  final Color? focusColor;

  ///  指针悬停时颜色
  final Color? hoverColor;

  ///  点击时的颜色
  final Color? highlightColor;

  ///  水波纹颜色
  final Color? splashColor;

  ///  自定义水波纹
  final InteractiveInkFeatureFactory? splashFactory;

  ///  水波纹半径
  final double? radius;

  /// 覆盖borderRadius的自定义剪辑边框
  final ShapeBorder? customBorder;

  /// 检测到的手势是否应该提供声音和/或触觉反馈，默认true
  final bool? enableFeedback;

  /// 焦点管理
  final FocusNode? focusNode;
  final bool? canRequestFocus;

  /// 焦点变化回调
  final ValueChanged<bool>? onFocusChange;

  /// 自动获取焦点
  final bool? autoFocus;
  BorderRadius? borderRadius;

  ///  ****** [Visibility] ******  ///
  final Widget replacement;
  final bool visible;

  @override
  Widget build(BuildContext context) {
    Widget current = const SizedBox();
    if (child != null) current = child!;//传入的child赋值给current
    if (children != null && children!.isNotEmpty) {
      current = isStack ? stackWidget(children!) : flexWidget(children!);
    }
    if (builder != null) current = statefulBuilder;
    if (margin != null) current = Padding(padding: margin!, child: current);
    if (shrink) current = SizedBox.shrink(child: current);
    if (expand) current = SizedBox.expand(child: current);
    if (width != null || height != null)
      current = SizedBox(width: width, height: height, child: current);
    if (size != null) current = SizedBox.fromSize(size: size, child: current);
    if (color != null) current = ColoredBox(color: color!, child: current);
    if (enabled ||
        onTap != null ||
        onDoubleTap != null ||
        onLongPress != null) {
      current =
          addInkWell ? inkWellWidget(current) : gestureDetectorWidget(current);
    }
    if (isScroll)
      current = noScrollBehavior
          ? ScrollConfiguration(behavior: const ScrollBehavior(),
          child: singleChildScrollViewWidget(current))
          : singleChildScrollViewWidget(current);
    if (opacity != null && opacity! > 0)
      current = Opacity(opacity: opacity!, child: current);
    if (!visible) current = visibilityWidget(current);
    return current;
  }

  Widget stackWidget(List<Widget> children) => Stack(
      alignment: alignment ?? AlignmentDirectional.topStart,
      textDirection: textDirection,
      fit: stackFit!,
      clipBehavior: clipBehavior ?? Clip.hardEdge,
      children: children);

  Widget flexWidget(List<Widget> children) => Flex(
      children: children,
      mainAxisAlignment: mainAxisAlignment!,
      crossAxisAlignment: crossAxisAlignment!,
      direction: direction,
      textBaseline: textBaseline,
      verticalDirection: verticalDirection,
      textDirection: textDirection,
      mainAxisSize: mainAxisSize!);

  Widget get statefulBuilder => StatefulBuilder(builder: builder!);

  Widget inkWellWidget(Widget current) => Ink(
      decoration: decoration,
      child: InkWell(
          child: current,
          onTap: onTap,
          onLongPress: onLongPress,
          onDoubleTap: onDoubleTap,
          onTapDown: onTapDown,
          onTapCancel: onTapCancel,
          onHighlightChanged: onHighlightChanged,
          onHover: onHover,
          focusColor: focusColor,
          hoverColor: hoverColor,
          highlightColor: highlightColor,
          splashColor: splashColor,
          splashFactory: splashFactory,
          radius: radius,
          borderRadius: borderRadius,
          customBorder: customBorder,
          enableFeedback: enableFeedback,
          excludeFromSemantics: excludeFromSemantics!,
          focusNode: focusNode,
          canRequestFocus: canRequestFocus!,
          onFocusChange: onFocusChange,
          autofocus: autoFocus!));

  Widget gestureDetectorWidget(Widget current) => GestureDetector(
      onTapDown: onTapDown,
      onTapUp: onTapUp,
      onTap: onTap,
      onTapCancel: onTapCancel,
      child: current);

  Widget singleChildScrollViewWidget(Widget current) {
    return SingleChildScrollView(
        physics: physics,
        reverse: reverse,
        primary: primary,
        controller: scrollController,
        scrollDirection: direction,
        clipBehavior: clipBehavior ?? Clip.hardEdge,
        child: current);
  }

  Widget visibilityWidget(Widget current) =>
      Visibility(child: current, replacement: replacement, visible: visible);
}
